home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / netArp.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  27KB  |  893 lines

  1. /* 
  2.  * netArp.c --
  3.  *
  4.  *    Routines for net arp and rarp.
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/netArp.c,v 1.8 92/06/03 22:47:47 voelker Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <sys.h>
  22. #include <stdlib.h>
  23. #include <timer.h>
  24. #include <sync.h>
  25. #include <rpc.h>
  26. #include <netInt.h>
  27. #include <netArp.h>
  28. #include <string.h>
  29. #include <stdio.h>
  30. #include <rpcClient.h>
  31. /*
  32.  * This flag turns on print statements in the ARP protocol
  33.  */
  34. Boolean arpDebug = FALSE;
  35.  
  36. ArpStatistics arpStatistics;
  37.  
  38. /*
  39.  * Current ARP transactions have their state linked together in
  40.  * a list so the packet handler can save the return address for
  41.  * the sender.
  42.  */
  43. static List_Links arpList;
  44. static List_Links revArpList;
  45. static Sync_Semaphore arpListMutex;
  46.  
  47. static ArpOutputQueue arpOutputQueue[ARP_OUTPUT_QUEUE_LEN];
  48. static int nextOutputIndex = 0;
  49.  
  50. static Sync_Lock arpOutputQueueLock; ;
  51. #define LOCKPTR (&arpOutputQueueLock)
  52. static ArpInputQueue arpInputQueue[ARP_INPUT_QUEUE_LEN];
  53. static int nextInputIndex = 0;
  54. static Sync_Semaphore arpInputMutex;
  55.  
  56. static    void    Net_ArpTimeout _ARGS_((Timer_Ticks time, ClientData data));
  57. static    void    NetArpHandler _ARGS_((ClientData data, 
  58.                 Proc_CallInfo *callInfoPtr));
  59. static    void    NetArpOutput _ARGS_((Net_Interface *interPtr,
  60.                 Net_EtherAddress *destEtherAddrPtr,
  61.                 int etherType, NetSpriteArp *requestPtr));
  62. static    void    NetFillInArpRequest _ARGS_((int command, 
  63.                 Net_NetworkType    netType, int protocol,
  64.                 ClientData targetId, ClientData senderId,
  65.                 Net_Address *targetAddrPtr, 
  66.                 Net_Address *senderAddrPtr, 
  67.                 NetSpriteArp *requestPtr));
  68.  
  69. /*
  70.  *----------------------------------------------------------------------
  71.  *
  72.  * Net_ArpInit --
  73.  *
  74.  *    Initializes the arp data structures.
  75.  *
  76.  * Results:
  77.  *    None.
  78.  *
  79.  * Side effects:
  80.  *    None.
  81.  *
  82.  *----------------------------------------------------------------------
  83.  */
  84.  
  85. void
  86. Net_ArpInit()
  87. {
  88.     int i;
  89.  
  90.     Sync_LockInitDynamic(&arpOutputQueueLock, "Net:arpOutputQueueLock");
  91.     Sync_SemInitDynamic(&arpInputMutex, "Net:arpInputMutex");
  92.     Sync_SemInitDynamic(&arpListMutex, "Net:arpListMutex"); 
  93.     /*
  94.      * Mark the arp output queue as all done (output).
  95.      */
  96.     for (i=0; i<ARP_OUTPUT_QUEUE_LEN ; i++) {
  97.     arpOutputQueue[i].gather.done = TRUE;
  98.     }
  99.     List_Init(&arpList);
  100.     List_Init(&revArpList);
  101. }
  102.  
  103.  
  104. /*
  105.  *----------------------------------------------------------------------
  106.  *
  107.  * Net_Arp --
  108.  *
  109.  *      Sprite's Address Resolution Protocol.  Broadcast a Sprite ARP
  110.  *      packet to find the physical address that is used to get to the
  111.  *      host identified by the Sprite ID.
  112.  *
  113.  * Results:
  114.  *    None.
  115.  *
  116.  * Side effects:
  117.  *    A broadcast, and the route table is updated.
  118.  *
  119.  *----------------------------------------------------------------------
  120.  */
  121.  
  122. ReturnStatus
  123. Net_Arp(spriteID, mutexPtr)
  124.     int    spriteID;            /* ID to find the route for */
  125.     Sync_Semaphore *mutexPtr;        /* Address of the mutex that the
  126.                      * caller of Net_Output used for
  127.                      * synchronization.  This needs to
  128.                      * be released during the ARP so that
  129.                      * we can receive our reply. */
  130. {
  131.     ReturnStatus status = FAILURE;
  132.     NetSpriteArp request;        /* The Sprite ARP request packet data */
  133.     NetSpriteArp reply;            /* The Sprite ARP reply packet data */
  134.     Net_ScatterGather gather;        /* Points to packet data */
  135.     Net_Interface *interPtr;
  136.     Net_Route    *routePtr;
  137.     int        i;
  138.  
  139.     for (i = 0; ; i++) {
  140.     routePtr = Net_IDToRoute(NET_BROADCAST_HOSTID, i, FALSE, 
  141.         (Sync_Semaphore *) NIL, 0);
  142.     if (routePtr == (Net_Route *) NIL) {
  143.         break;
  144.     }
  145.     interPtr = routePtr->interPtr;
  146.     NetFillInArpRequest(NET_ARP_REQUEST, interPtr->netType,
  147.         NET_PROTO_RAW,
  148.         (ClientData) spriteID, (ClientData) rpc_SpriteID, 
  149.         &interPtr->broadcastAddress, 
  150.         &interPtr->netAddress[NET_PROTO_RAW],
  151.         &request);
  152.     gather.bufAddr = (Address)&request;
  153.     gather.length = sizeof(NetSpriteArp);
  154.     gather.done = FALSE;
  155.     gather.mutexPtr = (Sync_Semaphore *) NIL;
  156.     
  157.     status = NetDoArp(routePtr, mutexPtr, NET_ARP_REQUEST, &gather, 
  158.             &reply);
  159.     Net_ReleaseRoute(routePtr);
  160.     if (status == SUCCESS) {
  161.         Net_Address netAddress;
  162.  
  163.         status = Net_SetAddress(NET_ADDRESS_ETHER, 
  164.                 (Address) ARP_SRC_ETHER_ADDR(&reply), &netAddress);
  165.         if (status != SUCCESS) {
  166.         panic("Net_Arp: Net_SetAddress failed\n");
  167.         }
  168.         (void) Net_InstallRoute(spriteID, interPtr, &netAddress,
  169.             NET_PROTO_RAW, "noname", "unknown", 0, RPC_MAX_SIZE,
  170.             (ClientData) 0);
  171.         return status;
  172.     }
  173.     }
  174.     return status;
  175. }
  176.  
  177. /*
  178.  *----------------------------------------------------------------------
  179.  *
  180.  * Net_RevArp --
  181.  *
  182.  *      Sprite's Reverse Address Resolution Protocol.  Broadcast a Sprite
  183.  *      Reverse ARP packet to find the Sprite ID or Internet address
  184.  *    that corresponds to our network address.
  185.  *
  186.  * Results:
  187.  *    A Sprite host ID
  188.  *
  189.  * Side effects:
  190.  *    None.
  191.  *
  192.  *----------------------------------------------------------------------
  193.  */
  194.  
  195. int
  196. Net_RevArp(routePtr, protocol, netAddressPtr, mutexPtr)
  197.     Net_Route        *routePtr;    /* The route to use for the arp.*/
  198.     int            protocol;    /* Which protocol we are trying
  199.                      * to resolve an address for. */
  200.     Net_Address        *netAddressPtr; /* The address we are trying to 
  201.                      * resolve. */
  202.     Sync_Semaphore    *mutexPtr;    /* Mutex to release. */
  203. {
  204.     ReturnStatus status;
  205.     NetSpriteArp request;        /* Sprite RARP request packet data */
  206.     NetSpriteArp reply;            /* Sprite RARP reply packet data */
  207.     Net_ScatterGather gather;        /* Points to packet data */
  208.     Net_Interface    *interPtr;
  209.  
  210.     interPtr = routePtr->interPtr;
  211.     if (netAddressPtr == (Net_Address *) NIL) {
  212.     netAddressPtr = &interPtr->netAddress[NET_PROTO_RAW];
  213.     }
  214.     NetFillInArpRequest(NET_RARP_REQUEST, interPtr->netType,
  215.         protocol, 
  216.         (ClientData) 0, (ClientData) 0,
  217.         netAddressPtr,
  218.         &interPtr->netAddress[NET_PROTO_RAW], 
  219.         &request);
  220.     gather.bufAddr = (Address)&request;
  221.     gather.length = sizeof(NetSpriteArp);
  222.     gather.done = FALSE;
  223.     gather.mutexPtr = (Sync_Semaphore *) NIL;
  224.  
  225.     status = NetDoArp(routePtr, mutexPtr, NET_RARP_REQUEST, &gather, 
  226.     &reply);
  227.     if (status == SUCCESS) {
  228.     unsigned int value;
  229.     bcopy(ARP_TARGET_PROTO_ADDR(&reply),(char *) &value,4);
  230.     return(Net_NetToHostInt(value));
  231.     } 
  232.     return -1;
  233. }
  234.  
  235. /*
  236.  *----------------------------------------------------------------------
  237.  *
  238.  * NetDoArp --
  239.  *
  240.  *    The broadcast-retry-wait loop for ARP and Reverse Arp.
  241.  *
  242.  * Results:
  243.  *    Fills in the callers packet buffer with a copy of the reply.
  244.  *    Returns FAILURE if there is no response after a timeout.
  245.  *
  246.  * Side effects:
  247.  *    The packet broadcast, wait, etc.
  248.  *
  249.  *----------------------------------------------------------------------
  250.  */
  251.  
  252. ReturnStatus
  253. NetDoArp(routePtr, mutexPtr, command, gatherPtr, packetPtr)
  254.     Net_Route        *routePtr;    /* The route to use for the arp. */
  255.     Sync_Semaphore *mutexPtr;        /* Address of the mutex that the
  256.                      * caller of Net_Output used for
  257.                      * synchronization.  This needs to
  258.                      * be released during the ARP so that
  259.                      * we can receive our reply. */
  260.     int command;            /* NET_ARP_REQUEST or NET_RARP_REQUEST*/
  261.     Net_ScatterGather *gatherPtr;    /* Specifies the output packet */
  262.     NetSpriteArp *packetPtr;        /* Filled in with the reply packet */
  263. {
  264.     register Net_EtherHdr *etherHdrPtr;    /* Regular RPC broadcast header */
  265.     Net_EtherHdr etherHdr;        /* Header for Sprite ARP packet */
  266.     int retries = 0;            /* Retry counter */
  267.     ArpState arp;            /* State for the protocol */
  268.     NetSpriteArp *requestPtr;        /* Pointer to request data */
  269.     List_Links *listPtr;        /* Either arpList or revArpList */
  270.     Net_Interface     *interPtr;    /* Network interface. */
  271.  
  272.     /*
  273.      * If we are aren't passed a mutexPtr then assume we can't do an
  274.      * Arp.  This is because we are either at interrupt level or there
  275.      * are high-level locks that cannot be released.
  276.      */
  277.     if (mutexPtr == (Sync_Semaphore *) NIL) {
  278.     return FAILURE;
  279.     }
  280.     if (Mach_AtInterruptLevel()) {
  281.     panic("NetDoArp: at interrupt level!!!");
  282.     }
  283.     interPtr = routePtr->interPtr;
  284.     switch(interPtr->netType) {
  285.     case NET_NETWORK_ETHER : {
  286.         /*
  287.          * Set up the ethernet header for the Arp request packet.  We can't
  288.          * use the regular broadcast route because the ethernet protocol 
  289.          * type is different, Arp.  The broadcast destination address,
  290.          * however, is obtained from the regular broadcast route.
  291.          */
  292.         etherHdrPtr = (Net_EtherHdr *)routePtr->headerPtr[NET_PROTO_RAW];
  293.         NET_ETHER_ADDR_COPY(NET_ETHER_HDR_DESTINATION(*etherHdrPtr),
  294.                 NET_ETHER_HDR_DESTINATION(etherHdr));
  295.         if (command == NET_ARP_REQUEST) {
  296.         NET_ETHER_HDR_TYPE(etherHdr) = 
  297.             Net_HostToNetShort(NET_ETHER_ARP);
  298.         } else {
  299.         NET_ETHER_HDR_TYPE(etherHdr) = 
  300.             Net_HostToNetShort(NET_ETHER_REVARP);
  301.         }
  302.         break;
  303.     }
  304.     default:
  305.         printf("NetDoArp :Invalid route (bad network type %d)\n", 
  306.         routePtr->interPtr->netType);
  307.         return FAILURE;
  308.     }
  309.     requestPtr = (NetSpriteArp *)gatherPtr->bufAddr;
  310.     /*
  311.      * Use a simple retry loop to get our reply.  The ARP protocol state
  312.      * is set up and put on a list so the packet handler can find it.
  313.      */
  314.  
  315.     arp.state = ARP_WANT_REPLY;
  316.     arp.mutexPtr = mutexPtr;
  317.     arp.type = Net_NetToHostShort((requestPtr->arpHeader.protocolType));
  318.  
  319.     if (command == NET_ARP_REQUEST) {
  320.     int spriteID;
  321.     bcopy(ARP_TARGET_PROTO_ADDR(requestPtr),(char *) &spriteID,4);
  322.     arp.id =  (ClientData) Net_NetToHostInt((unsigned int)spriteID);
  323.     listPtr = &arpList;
  324.     } else {
  325.     arp.id = (ClientData) ARP_TARGET_ETHER_ADDR(requestPtr);
  326.     listPtr = &revArpList;
  327.     }
  328.     MASTER_LOCK(&arpListMutex);
  329.     List_InitElement((List_Links *) &arp);
  330.     List_Insert((List_Links *)&arp, LIST_ATREAR(listPtr));
  331.     MASTER_UNLOCK(&arpListMutex);
  332.  
  333.     while (retries < 4 && ((arp.state & ARP_HAVE_INPUT) == 0)) {
  334.     retries++;
  335.     if (command == NET_ARP_REQUEST) {
  336.         if (arpDebug) {
  337.         printf("Sending arp request for %d\n", arp.id);
  338.         }
  339.         arpStatistics.numArpRequests++;
  340.     } else {
  341.         if (arpDebug) {
  342.         printf("Sending rev arp request\n");
  343.         }
  344.         arpStatistics.numRevArpRequests++;
  345.     }
  346.     (void) (interPtr->output)(interPtr, (Address) ðerHdr, gatherPtr, 1, 
  347.             FALSE, (ReturnStatus *) NIL);
  348.  
  349.     arp.state |= ARP_IN_TIMEOUT_QUEUE ;
  350.     arp.timeout.routine = Net_ArpTimeout;
  351.     arp.timeout.interval = 500 * timer_IntOneMillisecond;
  352.     arp.timeout.clientData = (ClientData)&arp;
  353.     Timer_ScheduleRoutine(&arp.timeout, TRUE);
  354.     do {
  355.         Sync_MasterWait(&arp.condition, arp.mutexPtr, FALSE);
  356.     } while (((arp.state & ARP_HAVE_INPUT) == 0) &&
  357.          (arp.state & ARP_IN_TIMEOUT_QUEUE));
  358.     }
  359.     MASTER_LOCK(&arpListMutex);
  360.     List_Remove((List_Links *)&arp);
  361.     MASTER_UNLOCK(&arpListMutex);
  362.     if (arp.state & ARP_IN_TIMEOUT_QUEUE) {
  363.     Timer_DescheduleRoutine(&arp.timeout);
  364.     }
  365.  
  366.     if ((arp.state & ARP_HAVE_INPUT) == 0) {
  367.     arpStatistics.numTimeouts++;
  368.     return(FAILURE);
  369.     } else {
  370.     *packetPtr = arp.packet;
  371.     return(SUCCESS);
  372.     }    
  373. }
  374.  
  375. /*
  376.  *----------------------------------------------------------------------
  377.  *
  378.  * NetArpInput --
  379.  *
  380.  *    Handler for the Address Resolution Protocol.  This looks through
  381.  *    the list of arpState's to find a match between the Sprite IDs.
  382.  *    Upon a match the physical address from the reply is stored in
  383.  *    the state and the waiting process is notified.
  384.  *
  385.  * Results:
  386.  *    None.
  387.  *
  388.  * Side effects:
  389.  *    Copies the data from the arp reply into the arp state that
  390.  *    was enqueued in arpList by Net_Arp.  The arpState is marked
  391.  *    as having received input.
  392.  *
  393.  *----------------------------------------------------------------------
  394.  */
  395.  
  396. /*ARGSUSED*/
  397. void
  398. NetArpInput(interPtr, packetPtr, packetLength)
  399.     Net_Interface    *interPtr;    /* The interface that got the 
  400.                      * packet. */
  401.     Address packetPtr;        /* Pointer to the packet in the hardware
  402.                  * recieve buffers */
  403.     int packetLength;        /* Length of the packet */
  404. {
  405.     register NetSpriteArp *arpDataPtr;
  406.     Boolean    forKernel = TRUE;
  407.     short opcode, type;
  408.     ReturnStatus status;
  409.  
  410.     switch(interPtr->netType) {
  411.     case NET_NETWORK_ETHER: {
  412.         arpDataPtr = (NetSpriteArp *)(packetPtr + sizeof(Net_EtherHdr));
  413.         break;
  414.     }
  415.     default :
  416.         return;
  417.     }
  418.     opcode = Net_NetToHostShort(arpDataPtr->arpHeader.opcode);
  419.     type = Net_NetToHostShort(arpDataPtr->arpHeader.protocolType);
  420.     /*
  421.      * This packet is for the kernel ARP if the following 
  422.      * condition are true:
  423.      *    1) The hardwareType of the request is for the ethernet.
  424.      *  2) The protocolType is ether for IP or Sprite type.
  425.      *  3) The opcode is one we can handle (1 thru 4).
  426.      */
  427.     forKernel = (Net_NetToHostShort(arpDataPtr->arpHeader.hardwareType) == 
  428.                         NET_ARP_TYPE_ETHER)      &&
  429.          ((type == NET_ETHER_IP) || (type == NET_ETHER_SPRITE)) &&
  430.          ((opcode > 0) && (opcode < 5)) ;
  431.  
  432.     if (!forKernel) {
  433.     return;
  434.     }
  435.  
  436.     switch (opcode) {
  437.     case NET_ARP_REQUEST: {
  438.         unsigned int id;
  439.         /*
  440.          * Received a request for the address corresponding to a
  441.          * sprite ID. Look to see if it is for us.
  442.          * If it is then we reply with that info.
  443.          */
  444.         bcopy(ARP_TARGET_PROTO_ADDR(arpDataPtr),(char *)&id,4);
  445.         id = Net_NetToHostInt(id);
  446.         if (arpDebug) {
  447.         printf("Got ARP request for Sprite ID 0x%x\n", id);
  448.         }
  449.         if (type == NET_ETHER_SPRITE) { 
  450.         forKernel = (id == rpc_SpriteID);
  451.         } else {
  452.         forKernel = 
  453.             (id == interPtr->netAddress[NET_PROTO_INET].address.inet);
  454.         }
  455.         if (forKernel) { 
  456.         /*
  457.          * We might overrun ourselves if we get a whole
  458.          * bunch of arp requests.  We synchronize, however,
  459.          * so that the call-back procedure sees a 
  460.          * consistent view.
  461.          */
  462.         register ArpInputQueue *arpInputPtr;
  463.         MASTER_LOCK(&arpInputMutex);
  464.         arpInputPtr = &arpInputQueue[nextInputIndex];
  465.         arpInputPtr->interPtr = interPtr;
  466.         arpInputPtr->packet = *arpDataPtr;
  467.         nextInputIndex = (nextInputIndex + 1) % ARP_INPUT_QUEUE_LEN;
  468.         MASTER_UNLOCK(&arpInputMutex);
  469.         Proc_CallFunc(NetArpHandler, (ClientData)arpInputPtr, 0);
  470.         }
  471.         break;
  472.     }
  473.     case NET_ARP_REPLY: {
  474.         ArpState *arpPtr;
  475.         unsigned int id;
  476.  
  477.         /*
  478.          * Make sure this REPLY is targeted for us.
  479.          */
  480.         if (Net_EtherAddrCmp(
  481.             interPtr->netAddress[NET_PROTO_RAW].address.ether,
  482.             (* ARP_TARGET_ETHER_ADDR(arpDataPtr)))) {
  483.         if (arpDebug) {
  484.             char    buf[20];
  485.             (void) Net_EtherAddrToString(
  486.             ARP_TARGET_ETHER_ADDR(arpDataPtr), buf);
  487.             printf("Ignoring reply for %s\n", buf);
  488.         }
  489.         break;
  490.         }
  491.  
  492.         /*
  493.          * Look through the list of active arp requests for the one
  494.          * that matches this reply.  Then just copy the arp data to
  495.          * that state and notify the waiting process.
  496.          * Note: we'll probably get many replies to each arp request
  497.          * and only the first one updates the waiting process's arp
  498.          * state.  This is probably overly paranoid, but we don't want
  499.          * to be messing with things once we've notified the waiter.
  500.          */
  501.         bcopy(ARP_SRC_PROTO_ADDR(arpDataPtr),(char *)&id,4);
  502.         id = Net_NetToHostInt(id);
  503.         if (arpDebug) {
  504.         printf("Got ARP reply for type %d Id 0x%x\n", type, id);
  505.         }
  506.         MASTER_LOCK(&arpListMutex);
  507.         LIST_FORALL(&arpList, (List_Links *)arpPtr) {
  508.         if ((arpPtr->id == (ClientData) id) && (arpPtr->type == type)) {
  509.             if ((arpPtr->state & ARP_HAVE_INPUT) == 0) {
  510.             arpPtr->packet = *arpDataPtr;
  511.             arpPtr->state |= ARP_HAVE_INPUT;
  512.             Sync_MasterBroadcast(&arpPtr->condition);
  513.             if (arpDebug) {
  514.                 printf("Woke ARP list type %d id %d\n",arpPtr->type,
  515.                 arpPtr->id);
  516.             }
  517.             }
  518.         }
  519.         }
  520.         MASTER_UNLOCK(&arpListMutex);
  521.         break;
  522.     }
  523.     case NET_RARP_REQUEST: {
  524.         /*
  525.          * Look in our route table for an entry with the ethernet
  526.          * address of the sender.  If one is found, return a reply
  527.          * containing the corresponding Sprite ID. The kernel only
  528.          * handles NET_ETHER_SPRITE requests.
  529.          */
  530.         int     spriteID;
  531.         Net_Address netAddress;
  532.  
  533.         if (type == NET_ETHER_SPRITE) { 
  534.         status = Net_SetAddress(NET_ADDRESS_ETHER, 
  535.             (Address) ARP_TARGET_ETHER_ADDR(arpDataPtr), &netAddress);
  536.         if (status != SUCCESS) {
  537.             panic("NetArpInput: Net_SetAddress failed\n");
  538.          }
  539.  
  540.         spriteID = Net_AddrToID(&netAddress);
  541.         if (arpDebug) {
  542.             printf("Got REV_ARP request for Sprite ID 0x%x\n",
  543.                 spriteID);
  544.         }
  545.         if (spriteID > 0) {
  546.             register ArpInputQueue *arpInputPtr;
  547.             MASTER_LOCK(&arpInputMutex);
  548.             arpInputPtr = &arpInputQueue[nextInputIndex];
  549.             arpInputPtr->interPtr = interPtr;
  550.             arpInputPtr->packet = *arpDataPtr;
  551.             nextInputIndex = (nextInputIndex + 1) % 
  552.                             ARP_INPUT_QUEUE_LEN;
  553.             MASTER_UNLOCK(&arpInputMutex);
  554.             Proc_CallFunc(NetArpHandler, (ClientData)arpInputPtr,0);
  555.         }
  556.          }
  557.         break;
  558.     }
  559.     case NET_RARP_REPLY: {
  560.         ArpState *arpPtr;
  561.  
  562.         if (Net_EtherAddrCmp(
  563.             interPtr->netAddress[NET_PROTO_RAW].address.ether,
  564.             (* ARP_TARGET_ETHER_ADDR(arpDataPtr)))) {
  565.         break;
  566.         }
  567.         /*
  568.          * Make sure there is still a waiting process for this reply,
  569.          * then copy the reply into the waiting arp state.
  570.          */
  571.         if (arpDebug) {
  572.           printf("Got REV_ARP reply for type %d\n",type);
  573.         }
  574.         MASTER_LOCK(&arpListMutex);
  575.         LIST_FORALL(&revArpList, (List_Links *)arpPtr) {
  576.         if ((arpPtr->type == type) && 
  577.            (!Net_EtherAddrCmpPtr(ARP_TARGET_ETHER_ADDR(arpDataPtr),
  578.                      (Net_EtherAddress *) (arpPtr->id)))) {
  579.             if ((arpPtr->state & ARP_HAVE_INPUT) == 0) {
  580.             arpPtr->packet = *arpDataPtr;
  581.             arpPtr->state |= ARP_HAVE_INPUT;
  582.             Sync_MasterBroadcast(&arpPtr->condition);
  583.             if (arpDebug) {
  584.               printf("Woke REV_ARP reply for type %d\n",type);
  585.             }
  586.             }
  587.         }
  588.         }
  589.         MASTER_UNLOCK(&arpListMutex);
  590.         break;
  591.     }
  592.     }
  593.     return;
  594. }
  595.  
  596. /*
  597.  *----------------------------------------------------------------------
  598.  *
  599.  * NetArpHandler --
  600.  *
  601.  *    Routine to send an arp reply.  Called via Proc_CallFunc.
  602.  *    This returns an ethernet address given a Sprite ID.  The
  603.  *    interrupt handler has already checked in the netRouteArray for
  604.  *    a good route for the spriteID.
  605.  *
  606.  * Results:
  607.  *    None.
  608.  *
  609.  * Side effects:
  610.  *    Generates a  arp reply packet.
  611.  *
  612.  *----------------------------------------------------------------------
  613.  */
  614. /*ARGSUSED*/
  615. static void
  616. NetArpHandler(data, callInfoPtr)
  617.     ClientData data;        /* Pointer into arpInputQueue */
  618.     Proc_CallInfo *callInfoPtr;
  619. {
  620.     Net_Interface    *interPtr;
  621.     ArpInputQueue *arpInputPtr = (ArpInputQueue *)data;
  622.     NetSpriteArp   *arpDataPtr, request;
  623.     unsigned short opcode, type;
  624.     ReturnStatus    status;
  625.  
  626.     MASTER_LOCK(&arpInputMutex);
  627.  
  628.     interPtr = arpInputPtr->interPtr;
  629.     arpDataPtr = &arpInputPtr->packet;
  630.     opcode = Net_NetToHostShort(arpDataPtr->arpHeader.opcode);
  631.     type = Net_NetToHostShort(arpDataPtr->arpHeader.protocolType);
  632.  
  633.     if ((type != NET_ETHER_SPRITE) && (type != NET_ETHER_IP)) {
  634.     MASTER_UNLOCK(&arpInputMutex);
  635.     panic("Bad type %d in NetArpHandler\n", type);
  636.     return;
  637.     } 
  638.     if (opcode == NET_ARP_REQUEST) {
  639.     Net_Address    netAddress;
  640.  
  641.     status = Net_SetAddress(NET_ADDRESS_ETHER, 
  642.             (Address) ARP_SRC_ETHER_ADDR(arpDataPtr), &netAddress);
  643.     if (status != SUCCESS) {
  644.         panic("NetArpHandler: Net_SetAddress failed\n");
  645.     }
  646.     if (type == NET_ETHER_SPRITE) {
  647.         int    spriteID;
  648.         bcopy(ARP_SRC_PROTO_ADDR(arpDataPtr),(char*)&spriteID,sizeof(int));
  649.  
  650.         NetFillInArpRequest(NET_ARP_REPLY, interPtr->netType,
  651.         NET_PROTO_RAW,
  652.         (ClientData) spriteID, (ClientData) rpc_SpriteID, 
  653.         &netAddress, &interPtr->netAddress[NET_PROTO_RAW],
  654.         &request);
  655.     } else {
  656.         Net_Address        inetAddress;
  657.         Net_InetAddress     tmp;
  658.         bcopy(ARP_SRC_PROTO_ADDR(arpDataPtr), (char *)&tmp, 
  659.             sizeof(Net_InetAddress));
  660.         status = Net_SetAddress(NET_ADDRESS_INET, (Address) &tmp, 
  661.         &inetAddress);
  662.         if (status != SUCCESS) {
  663.         panic("NetArpHandler: Net_SetAddress failed\n");
  664.         }
  665.         NetFillInArpRequest(NET_ARP_REPLY, interPtr->netType, 
  666.         NET_PROTO_INET,
  667.         (ClientData) inetAddress.address.inet, 
  668.         (ClientData) interPtr->netAddress[NET_PROTO_INET].address.inet, 
  669.         &netAddress, &interPtr->netAddress[NET_PROTO_RAW],
  670.         &request);
  671.     }
  672.         NetArpOutput(interPtr, &netAddress.address.ether, NET_ETHER_ARP, 
  673.         &request);
  674.     } else if (opcode == NET_RARP_REQUEST) {
  675.     Net_Address netAddress;
  676.     int    spriteID;
  677.  
  678.     status = Net_SetAddress(NET_ADDRESS_ETHER, 
  679.         (Address) ARP_TARGET_ETHER_ADDR(arpDataPtr), &netAddress);
  680.     if (status != SUCCESS) {
  681.         panic("NetArpHandler: Net_SetAddress failed\n");
  682.     }
  683.     spriteID = Net_AddrToID(&netAddress);
  684.     if (spriteID > 0) { 
  685.         NetFillInArpRequest(NET_RARP_REPLY, interPtr->netType,
  686.             NET_PROTO_RAW,
  687.             (ClientData) spriteID, (ClientData) rpc_SpriteID,
  688.             &netAddress, &interPtr->netAddress[NET_PROTO_RAW],
  689.             &request);
  690.         NetArpOutput(interPtr, ARP_SRC_ETHER_ADDR(arpDataPtr),
  691.             NET_ETHER_REVARP, &request);
  692.     }
  693.     } else {
  694.     MASTER_UNLOCK(&arpInputMutex);
  695.     panic ("Bad opcode %d in NetArpHandler\n", opcode);
  696.     return;
  697.     }
  698.     MASTER_UNLOCK(&arpInputMutex);
  699.  
  700.     callInfoPtr->interval = 0;
  701.     return;
  702. }
  703.  
  704. /*
  705.  *----------------------------------------------------------------------
  706.  *
  707.  * NetArpOutput --
  708.  *
  709.  *    Routine to send an arp packet.
  710.  *
  711.  * Results:
  712.  *    None.
  713.  *
  714.  * Side effects:
  715.  *    Generates a Sprite arp packet.
  716.  *
  717.  *----------------------------------------------------------------------
  718.  */
  719. /*ARGSUSED*/
  720. static void
  721. NetArpOutput(interPtr, destEtherAddrPtr, etherType, requestPtr)
  722.     Net_Interface    *interPtr;
  723.     Net_EtherAddress *destEtherAddrPtr;    /* Host to send to */
  724.     int        etherType;        /* Type of ethernet packet to send. */
  725.     NetSpriteArp *requestPtr;        /* Request to send. */
  726. {
  727.     register Net_EtherHdr  *etherHdrPtr;
  728.     register Net_ScatterGather *gatherPtr;
  729.     register NetSpriteArp *packetPtr;
  730.  
  731.     if (interPtr->netType != NET_NETWORK_ETHER) {
  732.     printf("NetArpOutput: invalid network type %d\n", interPtr->netType);
  733.     return;
  734.     }
  735.     LOCK_MONITOR;
  736.  
  737.  
  738.     etherHdrPtr = &arpOutputQueue[nextOutputIndex].etherHdr;
  739.     packetPtr = &arpOutputQueue[nextOutputIndex].packet;
  740.     gatherPtr = &arpOutputQueue[nextOutputIndex].gather;
  741.     if (! gatherPtr->done) {
  742.     printf("Warning: NetArpOutput can't queue packet");
  743.     UNLOCK_MONITOR;
  744.     return;
  745.     }
  746.     nextOutputIndex = (nextOutputIndex + 1) % ARP_OUTPUT_QUEUE_LEN;
  747.  
  748.     NET_ETHER_ADDR_COPY(*destEtherAddrPtr, 
  749.             NET_ETHER_HDR_DESTINATION(*etherHdrPtr));
  750.     NET_ETHER_HDR_TYPE(*etherHdrPtr) = 
  751.         Net_HostToNetShort((unsigned short)etherType);
  752. #ifdef sun4
  753.     /*
  754.      * Gcc for the sun4 currently allows these structures to be on unaligned
  755.      * boundaries and then generates loads and stores as if they were aligned,
  756.      * so I have to copy them byte by byte.
  757.      */
  758.      bcopy((char *)requestPtr, (char *)packetPtr, sizeof (NetSpriteArp));
  759. #else
  760.     *packetPtr = *requestPtr;
  761. #endif sun4
  762.  
  763.     gatherPtr->bufAddr = (Address)packetPtr;
  764.     gatherPtr->length = sizeof(NetSpriteArp);
  765.     gatherPtr->done = FALSE;
  766.     gatherPtr->mutexPtr = (Sync_Semaphore *) NIL;
  767.  
  768.     arpStatistics.numRevArpReplies++;
  769.     (void) (interPtr->output)(interPtr, (Address) etherHdrPtr, gatherPtr, 1, 
  770.     FALSE, (ReturnStatus *) NIL);
  771.  
  772.     UNLOCK_MONITOR;
  773.     return;
  774. }
  775.  
  776. /*
  777.  *----------------------------------------------------------------------
  778.  *
  779.  * Net_ArpTimeout --
  780.  *
  781.  *    Timeout routine for ARP.  This just notifies the waiting process.
  782.  *
  783.  * Results:
  784.  *    None.
  785.  *
  786.  * Side effects:
  787.  *    Wakes up the process waiting for an ARP reply.
  788.  *
  789.  *----------------------------------------------------------------------
  790.  */
  791. /*ARGSUSED*/
  792. static void
  793. Net_ArpTimeout(time, data)
  794.     Timer_Ticks time;        /* The time we timed out at. */
  795.     ClientData data;        /* Out private data is a pointer to the
  796.                  * arp protocol state. */
  797. {
  798.     ArpState *arpPtr = (ArpState *)data;    
  799.  
  800.     MASTER_LOCK(arpPtr->mutexPtr);
  801.     if (arpDebug) {
  802.     printf("Arp timeout\n");
  803.     }
  804.     arpPtr->state &= ~ARP_IN_TIMEOUT_QUEUE;
  805.     Sync_MasterBroadcast(&arpPtr->condition);
  806.     MASTER_UNLOCK(arpPtr->mutexPtr);
  807.     return;
  808. }
  809.  
  810. /*
  811.  *----------------------------------------------------------------------
  812.  *
  813.  * NetFillInArpRequest --
  814.  *
  815.  *     Build a ARP or RARP packet in the provided request buffer.
  816.  *
  817.  * Results:
  818.  *    None.
  819.  *
  820.  * Side effects:
  821.  *    None.
  822.  *
  823.  *----------------------------------------------------------------------
  824.  */
  825.  
  826. static void
  827. NetFillInArpRequest(command, netType, protocol, targetId, senderId, 
  828.     targetAddrPtr, senderAddrPtr, requestPtr)
  829.     short    command;    /* ARP opcode to perform. */
  830.     Net_NetworkType    netType;
  831.     int            protocol;
  832.     ClientData    targetId;    /* Target protocol address. */
  833.     ClientData  senderId;    /* Sender's protocol ID. */
  834.     Net_Address    *targetAddrPtr; /* Target network address. */
  835.     Net_Address    *senderAddrPtr; /* Sender'network address. */
  836.     NetSpriteArp *requestPtr;    /* Arp request packet to fill in. */
  837. {
  838.     unsigned int     tid;
  839.     unsigned int     sid;
  840.     ReturnStatus    status;
  841.  
  842.     switch (netType) {
  843.     case NET_NETWORK_ETHER: {
  844.         requestPtr->arpHeader.hardwareType = 
  845.             Net_HostToNetShort(NET_ARP_TYPE_ETHER);
  846.         requestPtr->arpHeader.hardwareAddrLen = sizeof(Net_EtherAddress);
  847.         requestPtr->arpHeader.opcode = 
  848.             Net_HostToNetShort((unsigned short)command);
  849.         switch (protocol) {
  850.         case NET_PROTO_RAW: {
  851.             requestPtr->arpHeader.protocolType = 
  852.                 Net_HostToNetShort(NET_ETHER_SPRITE);
  853.             requestPtr->arpHeader.protocolAddrLen = sizeof(int);
  854.             break;
  855.         }
  856.         case NET_PROTO_INET: {
  857.             requestPtr->arpHeader.protocolType = 
  858.                 Net_HostToNetShort(NET_ETHER_IP);
  859.             requestPtr->arpHeader.protocolAddrLen = 
  860.             sizeof(Net_InetAddress);
  861.             break;
  862.         }
  863.         default:
  864.             panic("NetFillInArpRequest: Unknown protocol %d\n", 
  865.             protocol);
  866.         }
  867.         status = Net_GetAddress(targetAddrPtr, 
  868.         (Address) ARP_TARGET_ETHER_ADDR(requestPtr));
  869.         if (status != SUCCESS) {
  870.         printf(
  871.         "NetFillInArpRequest: Net_GetAddress of target address failed\n");
  872.         return;
  873.         }
  874.         status = Net_GetAddress(senderAddrPtr, 
  875.         (Address) ARP_SRC_ETHER_ADDR(requestPtr));
  876.         if (status != SUCCESS) {
  877.         printf(
  878.         "NetFillInArpRequest: Net_GetAddress of sender address failed\n");
  879.         return;
  880.         }
  881.         break;
  882.     }
  883.     default: {
  884.         panic("Warning: NetFillInArpRequest: bad netType %d\n", netType);
  885.     }
  886.     }
  887.     tid = Net_HostToNetInt((unsigned int) targetId);
  888.     sid = Net_HostToNetInt((unsigned int) senderId);
  889.     bcopy((char *) &sid, ARP_SRC_PROTO_ADDR(requestPtr),sizeof(int));
  890.     bcopy((char *) &tid, ARP_TARGET_PROTO_ADDR(requestPtr),sizeof(int));
  891.     return;
  892. }
  893.